package com.zmn.plat.services.impl.product;

import com.zmn.common.dto.StatusDTO;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.plat.manager.dictionary.ProductDict;
import com.zmn.plat.model.dto.product.ProductRelationDTO;
import com.zmn.plat.model.entity.category.ServCategAndCategTwoQuery;
import com.zmn.plat.model.entity.product.ProductQuery;
import com.zmn.plat.model.entity.product.ServProduct;
import com.zmn.plat.model.entity.product.ServProductQuery;
import com.zmn.plat.model.entity.product.tariff.item.ProductTariffGroupItemQuery;
import com.zmn.plat.model.vo.channel.ChannelServProductVO;
import com.zmn.plat.model.vo.product.ProductAllMsgVO;
import com.zmn.plat.model.vo.product.ServProductBackVO;
import com.zmn.plat.model.vo.product.ServProductStatusVO;
import com.zmn.plat.model.vo.product.emissions.ProductEmissionsVO;
import com.zmn.plat.model.vo.product.tariff.item.ProductTariffGroupItemVo;
import com.zmn.plat.persistence.interfaces.product.ServProductDAO;
import com.zmn.plat.services.interfaces.product.ServProductService;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * 描述:ServProductServiceImpl
 *
 * @author tanghongjun
 * @since: 2018/10/16 17:56
 */
@Service
public class ServProductServiceImpl implements ServProductService {

    @Resource
    private ServProductDAO servProductDAO;

    @Override
    public ServProduct findByKey(Integer productId) {
        return servProductDAO.findByKey(productId);
    }

    @Override
    public Integer findTotalEmissionsByShowProductId(Integer showProductId) {
        return servProductDAO.findTotalEmissionsByShowProductId(showProductId);
    }

    @Override
    public ProductAllMsgVO findAllMsgByKey(Integer productId) {
        return servProductDAO.findAllMsgByKey(productId);
    }

    @Override
    @Cacheable(key = "'service:product:key:' + #p0", cacheNames = "redis1h")
    public ServProduct findByKeyWithCache(Integer productId) {
        return servProductDAO.findByKey(productId);
    }

    @Override
    public ServProduct findShowProductByBackProductId(Integer productId) {
        if (productId == null) {
            return null;
        }
        List<ServProduct> productList = listShowProductByBackProductId(Arrays.asList(productId));
        return CollectionUtils.isEmpty(productList) ? null : productList.get(0);
    }

    @Override
    public ServProduct findTariffProductByBackProductId(Integer productId) {
        if (productId == null) {
            return null;
        }
        List<ServProduct> productList = listTariffProductByBackProductId(Arrays.asList(productId));
        return CollectionUtils.isEmpty(productList) ? null : productList.get(0);
    }

    @Override
    public List<ProductAllMsgVO> listAllMsgByKeys(List<Integer> productIdList) {
        return servProductDAO.listAllMsgByKeys(productIdList);
    }

    @Override
    public List<ProductAllMsgVO> listAllMsgByProductQuery(ProductQuery productQuery) {
        return servProductDAO.listAllMsgByProductQuery(productQuery);
    }

    @Override
    public List<ServProduct> listByName(String name, Integer showType) {
        return servProductDAO.listByName(name, showType);
    }

    @Override
    public List<ServProduct> listByNameList(List<String> nameList, Integer showType) {
        if (CollectionUtils.isEmpty(nameList)) {
            return Collections.emptyList();
        }
        return servProductDAO.listByNameList(nameList, showType);
    }

    @Override
    public List<ServProduct> listShowProductSatisfyFaultRule(Integer channelId) {
        return servProductDAO.listShowProductSatisfyFaultRule(channelId);
    }

    @Override
    public List<Integer> findCategIds(Integer servCategId, Integer status, Integer outsideUse) {
        return servProductDAO.findCategIds(servCategId, status, outsideUse);
    }

    @Override
    public Integer findKeyForMax() {
        return servProductDAO.findKeyForMax();
    }

    @Override
    public Integer findMaxShowSort() {
        return servProductDAO.findMaxShowSort();
    }

    @Override
    public List<ServProduct> listPageByQuery(ServProductQuery query) {
        return servProductDAO.listPageByQuery(query);
    }

    @Override
    public List<ServProduct> listPageByQueryForShow(ServProductQuery query) {
        return servProductDAO.listPageByQueryForShow(query);
    }

    @Override
    public List<ServProduct> listPageByQueryForTariff(ServProductQuery query) {
        return servProductDAO.listPageByQueryForTariff(query);
    }

    @Override
    public List<ServProduct> listPageByQueryForShowByCategSort(ServProductQuery query) {
        return servProductDAO.listPageByQueryForShowByCategSort(query);
    }

    @Override
    public List<ServProduct> listProductHasRelated(List<Integer> productIds) {
        return servProductDAO.listProductHasRelated(productIds);
    }

    @Override
    public List<ServProductStatusVO> listProductStatusByProductIds(List<Integer> productIds) {
        return servProductDAO.listProductStatusByProductIds(productIds);
    }

    /**
     * 功能描述 ：根据后台产品查询相关联的前台产品下关联的所有后台产品
     *
     * @param productIds
     * @return List<ServProduct>
     * @author tanbiao
     * @since 2019/10/24
     * @modifier
     */
    @Override
    public List<ServProductBackVO> listByProductIds(List<Integer> productIds) {
        return servProductDAO.listByProductIds(productIds);
    }

    /**
     * 功能描述 ：根据后台产品查询相关联的计价器产品下关联的所有后台产品
     *
     * @param productIds
     * @return List<ServProduct>
     * @author tanbiao
     * @since 2019/10/24
     * @modifier
     */
    @Override
    public List<ServProductBackVO> listTariffRelationBackProductsByProductIds(List<Integer> productIds) {
        return servProductDAO.listTariffRelationBackProductsByProductIds(productIds);
    }

    @Override
    public List<ServProductBackVO> listProductHasRelatedForShow(List<Integer> productIds) {
        // 只有关联关系，需要筛选一下：1.未关联，2.已关联，但是存在部分上架部分下架的后台产品需要排除
        // sql内部做了前台产品id,后台产品状态的排序操作，因此同一个前台产品最多存在两条数据
        List<ServProductBackVO> list = servProductDAO.listProductHasRelatedForShow(productIds);
        List<ServProductBackVO> result = filterProduct(list);
        return result;
    }

    @Override
    public List<ServProductBackVO> listProductHasRelatedForTariff(List<Integer> productIds) {
        // 只有关联关系，需要筛选一下：1.未关联，2.已关联，但是存在部分上架部分下架的后台产品需要排除
        // sql内部做了前台产品id,后台产品状态的排序操作，因此同一个前台产品最多存在两条数据
        List<ServProductBackVO> list = servProductDAO.listProductHasRelatedForTariff(productIds);
        List<ServProductBackVO> result = filterProduct(list);
        return result;
    }

    private List<ServProductBackVO> filterProduct(List<ServProductBackVO> list) {
        List<ServProductBackVO> result = new ArrayList<>();
        Map<Integer, List<ServProductBackVO>> filterMap = new HashMap<>();
        list.forEach(e -> {
            // 没有关联关系的
            if (null == e.getShowProductId()) {
                result.add(e);
            } else {
                // 存在关联的数据,检查是否是部分开启的后台产品
                if (filterMap.get(e.getProductId()) == null) {
                    List<ServProductBackVO> products = new ArrayList<>();
                    products.add(e);
                    filterMap.put(e.getProductId(), products);
                } else {
                    filterMap.get(e.getProductId()).add(e);
                }
            }
        });
        filterMap.forEach((k, v) -> {
            if (v.size() == 1) {
                Integer status = v.get(0).getStatus();
                if (status != null && status.equals(ProductDict.STATUS_DISABLE)) {
                    result.add(v.get(0));
                }
            }
        });
        return result;
    }

    @Override
    public List<ServProductBackVO> listPageByQueryForBackProduct(ServProductQuery query) {
        return servProductDAO.listPageByQueryForBackProduct(query);
    }

    @Override
    public List<ServProductBackVO> listPageByQueryForBackProductByCategSort(ServProductQuery query) {
        return servProductDAO.listPageByQueryForBackProductByCategSort(query);
    }

    @Override
    public List<ServProduct> listPageByQueryForTariffByCategSort(ServProductQuery query) {
        return servProductDAO.listPageByQueryForTariffByCategSort(query);
    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'product:listByQuery:ServProductQuery:'+#p0", unless = "#result == null")
    public List<ServProduct> listByQuery(ServProductQuery query) {
        return servProductDAO.listByQuery(query);
    }

    @Override
    public List<ServProduct> listByIdList(List<Integer> productIdList) {
        if (productIdList.size() == 0) {
            return Collections.EMPTY_LIST;
        }
        return servProductDAO.listByIdList(productIdList);
    }

    @Override
    public List<ServProduct> listByIdList(List<Integer> productIdList, Integer status) {
        if (productIdList.size() == 0) {
            return Collections.EMPTY_LIST;
        }
        return servProductDAO.listByIdListAndStatus(productIdList, status);
    }

    @Override
    public List<ServProduct> listAll() {
        return servProductDAO.listAll();
    }

    @Override
    public List<Integer> listAllIds() {
        return servProductDAO.listAllIds();
    }

    @Override
    public List<ServProduct> findAllProductByServProductList(List<ServProductQuery> servProductList) {
        return servProductDAO.findAllProductByServProductList(servProductList);
    }

    @Override
    public List<ServProduct> listSupportByShowProductId(Integer showProductId) {
        return servProductDAO.listSupportByShowProductId(showProductId);
    }

    @Override
    public List<ServProduct> listSupportByTariffProductId(Integer traiffProductId) {
        return servProductDAO.listSupportByTariffProductId(traiffProductId);
    }

    @Override
    public List<ServProduct> listNormalBackProductByShowProductId(Integer showProductId) {
        return servProductDAO.listNormalBackProductByShowProductId(showProductId);
    }

    @Override
    public List<ServProduct> listNormalBackProductByTariffProductId(Integer traiffProductId) {
        return servProductDAO.listNormalBackProductByTariffProductId(traiffProductId);
    }

    @Override
    public List<ProductTariffGroupItemVo> listProductHasTariffByQuery(ProductTariffGroupItemQuery productFaultItemQuery) {
        return servProductDAO.listProductHasTariffByQuery(productFaultItemQuery);
    }

    @Override
    public List<ServProduct> listProductSupportTariff(List<Integer> productIdList) {
        return servProductDAO.listProductSupportTariff(productIdList);
    }

    @Override
    public List<ServProduct> listProductSupportServ(List<Integer> productIdList) {
        return servProductDAO.listProductSupportServ(productIdList);
    }

    @Override
    public List<ServProduct> listShowProductSupportTariff(List<Integer> productIdList) {
        return servProductDAO.listShowProductSupportTariff(productIdList);
    }

    @Override
    public List<ServProduct> listShowProductSupportServ(List<Integer> productIdList) {
        return servProductDAO.listShowProductSupportServ(productIdList);
    }

    @Override
    public List<ServProduct> listBackProductByShowProductId(Integer productId) {
        if (productId == null) {
            return Collections.EMPTY_LIST;
        }
        return servProductDAO.listBackProductByShowProductId(productId);
    }

    @Override
    public List<Integer> listUnRelatedProductGroupByProductIdList(List<Integer> productIds) {
        if (CollectionUtils.isEmpty(productIds)) {
            return Collections.EMPTY_LIST;
        }
        return servProductDAO.listUnRelatedProductGroupByProductIdList(productIds);
    }

    @Override
    public List<ServProduct> listShowProductByBackProductId(List<Integer> productIds) {
        if (CollectionUtils.isEmpty(productIds)) {
            return Collections.EMPTY_LIST;
        }
        return servProductDAO.listShowProductByBackProductId(productIds);
    }

    @Override
    public List<ProductAllMsgVO> listByShowTypeAndServCategAndCategAndStatus(Integer showType, Integer servCategId, Integer categTwoId, Integer status) {
        return servProductDAO.listByShowTypeAndServCategAndCategAndStatus(showType, servCategId, categTwoId, status);
    }

    @Override
    public List<ServProduct> listBackProductByTariffProductId(Integer productId) {
        if (productId == null) {
            return Collections.EMPTY_LIST;
        }
        return servProductDAO.listBackProductByTariffProductId(productId);
    }

    @Override
    public List<ServProduct> listTariffProductByBackProductId(List<Integer> productIds) {
        if (CollectionUtils.isEmpty(productIds)) {
            return Collections.EMPTY_LIST;
        }
        return servProductDAO.listTariffProductByBackProductId(productIds);
    }

    @Override
    public List<ProductRelationDTO> listProductRalationByIdListAndShowType(List<Integer> productIdList, Integer showType) {
        if (CollectionUtils.isEmpty(productIdList)) {
            return Collections.EMPTY_LIST;
        }
        return servProductDAO.listProductRalationByIdListAndShowType(productIdList,showType);
    }

    @Override
    public List<ServProduct> listChannelSupportProductsByCategIds(List<ServCategAndCategTwoQuery> servCategAndCategTwoQueries, Integer channelId) {
        if (CollectionUtils.isEmpty(servCategAndCategTwoQueries)) {
            return Collections.EMPTY_LIST;
        }
        return servProductDAO.listChannelSupportProductsByCategIds(servCategAndCategTwoQueries,channelId);
    }

    @Override
    public List<ProductEmissionsVO> listTotalEmissionsByShowProductIdList(List<Integer> showProductIds) {
        if (CollectionUtils.isEmpty(showProductIds)) {
            return Collections.EMPTY_LIST;
        }
        return servProductDAO.listTotalEmissionsByShowProductIdList(showProductIds);
    }

    @Override
    public List<ChannelServProductVO> listChannelServProductByQuery(ServProductQuery query) {

        return servProductDAO.listChannelServProductByQuery(query);
    }

    @Override
    public List<ProductAllMsgVO> listProductByQuery(ProductQuery query) {
        return servProductDAO.listProductByQuery(query);
    }

    @Override
    public Integer countByQuery(ServProductQuery query) {
        return servProductDAO.countByQuery(query);
    }

    @Override
    public int countByQueryForBackProduct(ServProductQuery query) {
        return servProductDAO.countByQueryForBackProduct(query);
    }

    @Override
    public int countByQueryForShow(ServProductQuery query) {
        return servProductDAO.countByQueryForShow(query);
    }

    @Override
    public int countByQueryForTariff(ServProductQuery query) {
        return servProductDAO.countByQueryForTariff(query);
    }

    @Override
    public Integer updateByKey(ServProduct servProduct) {
        return servProductDAO.updateByKey(servProduct);
    }

    @Override
    public Integer updateStatus(ServProduct servProduct) {
        return servProductDAO.updateStatus(servProduct);
    }

    @Override
    public void updateSortByKey(Integer productId, Integer sort, String updater) {
        ServProduct servProduct = new ServProduct();
        servProduct.setProductId(productId);
        servProduct.setSort(sort);
        servProduct.setUpdater(updater);
        servProduct.setUpdateTime(DateUtil.getNow());
        servProductDAO.updateSortByKey(servProduct);
    }

    @Override
    public void updateShowSortByKey(Integer productId, Integer sort, String mcStaffRealName) {
        ServProduct servProduct = new ServProduct();
        servProduct.setProductId(productId);
        servProduct.setShowSort(sort);
        servProduct.setSort(sort);
        servProduct.setUpdater(mcStaffRealName);
        servProduct.setUpdateTime(DateUtil.getNow());
        servProductDAO.updateShowSortByKey(servProduct);
    }

    @Override
    public void updateTotalEmissionsByKeys(List<Integer> ids, Integer totalEmissions, String updater) {
        servProductDAO.updateTotalEmissionsByKeys(ids, totalEmissions, updater, DateUtil.getNow());
    }

    @Override
    public Integer updateStatusBatch(StatusDTO dto) {
        return servProductDAO.updateStatusBatch(dto);
    }

    @Override
    public Integer updateTariffStatusBatch(ServProduct servProduct) {
        return servProductDAO.updateTariffStatusBatch(servProduct);
    }

    @Override
    public Integer updateProductDescByCategIds(String productDesc, List<ServCategAndCategTwoQuery> categIds, String opeator) {
        return servProductDAO.updateProductDescByCategIds(productDesc,categIds,opeator);
    }

    @Override
    public Integer insert(ServProduct servProduct) {
        return servProductDAO.insert(servProduct);
    }

    @Override
    public Integer deleteByKey(Integer productId) {
        return servProductDAO.deleteByKey(productId);
    }

    @Override
    public String translateShowPlatStrByShowPlat(String showPlat) {
        List<Integer> showPlats = StringUtil.convertStrsToList(showPlat);
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < showPlats.size(); i++) {
            if (i == showPlats.size() - 1) {
                stringBuilder.append(ProductDict.getShowPlatName(showPlats.get(i)));
            } else {
                stringBuilder.append(ProductDict.getShowPlatName(showPlats.get(i))).append(",");
            }
        }
        return stringBuilder.toString();
    }

    @Override
    public String translateBizTypeStrByBizType(String bizType) {
        String[] tmpIds = bizType.split("\\$");
        List<Integer> showPlats = new ArrayList<>(tmpIds.length);
        for (String tmpId : tmpIds) {
            if (StringUtil.isBlank(tmpId.trim())) {
                continue;
            }
            showPlats.add(Integer.parseInt(tmpId.trim()));
        }

        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < showPlats.size(); i++) {
            if (i == showPlats.size() - 1) {
                stringBuilder.append(com.zmn.plat.common.dictionary.ProductDict.getBizTypeCNENName(showPlats.get(i)));
            } else {
                stringBuilder.append(com.zmn.plat.common.dictionary.ProductDict.getBizTypeCNENName(showPlats.get(i))).append(",");
            }
        }
        return stringBuilder.toString();
    }

}
